package org.amos.security.handler;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Dict;
import jakarta.annotation.PostConstruct;
import lombok.SneakyThrows;
import org.amos.core.basic.annotation.Log;
import org.amos.core.basic.exception.ServiceException;
import org.amos.core.basic.utils.HttpUtils;
import org.amos.security.authentication.Authenticator;
import org.amos.security.domain.bo.AuthInfo;
import org.amos.security.enums.UserStateEnums;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.amos.security.constants.AuthConstant.AUTH_TYPE;

/**
 * @desc: 系统授权认证管理器
 * @author: liubt
 * @date: 2022-08-15 11:13
 **/
@Component
public class AmosAuth implements AuthManager {

    @Autowired(required = false)
    private Set<Authenticator> authenticators;

    private Map<Integer, Authenticator> authHandlerMap = new HashMap<>();

    @Override
    @PostConstruct
    public void init() {
        if (CollUtil.isNotEmpty(authenticators)) {
            authenticators.stream().collect(Collectors.toMap(Authenticator::authType, Function.identity())).forEach((k, v) -> authHandlerMap.putIfAbsent(k, v));
        }
    }

    @SneakyThrows
    @Override
    @Log("[AmosAuth]执行登录")
    public AuthInfo login(Dict param) {
        String deviceName = HttpUtils.getDeviceName();
        Integer authType = param.getInt(AUTH_TYPE);
        Assert.notNull(authType, "authType can not null");
        Authenticator authHandler = authHandlerMap.get(authType);
        if (Objects.isNull(authHandler)) {
            return new AuthInfo();
        }
        AuthInfo authInfo = authHandler.postHandle(param);
        if (Objects.isNull(authInfo)) {
            throw new ServiceException("用户身份认证异常");
        }
        if (UserStateEnums.NOT_INIT.getCode().equals(authInfo.getStatus())) {
            throw new ServiceException("该账号未启用,请联系管理员!");
        }
        if (UserStateEnums.DISABLE.getCode().equals(authInfo.getStatus())) {
            throw new ServiceException("该账号已封禁!");
        }
        SaLoginModel model = new SaLoginModel();
        model.setDevice(deviceName);
//        model.setTimeout(AuthConstant.TOKEN_EXPIRE);
        // 校验指定账号是否已被封禁(只校验临时封禁)
        StpUtil.checkDisable(authInfo.getId());
        StpUtil.login(authInfo.getId(), model);
        StpUtil.getSession().set(SaSession.USER, authInfo);
        authInfo.setToken(StpUtil.getTokenValue());
        authInfo.setExpire(StpUtil.getTokenTimeout());
        return authInfo;
    }

    @Override
    public Boolean isLogin(Dict param) {
        return null;
    }

    @Override
    public Boolean logout(Dict param) {
        return null;
    }
}
